
#include <gmock/gmock.h>
#include "Common.pb.h"
#include "Common.grpc.pb.h"
#include <grpcpp/grpcpp.h>

using grpc::Server;
using grpc::ServerBuilder;
using grpc::ServerContext;
using grpc::Status;
class SendService final : public gameRpcProctoc::ExampleService::Service
{
public:
	Status SayHello(::grpc::ServerContext *context, const ::gameRpcProctoc::Request *request, ::gameRpcProctoc::Response *response)
	{
		std::string req = request->message();
		if (req == "world")
		{
			std::string respond("hello");
			response->set_message(respond);
			return Status::OK;
		}
		else
		{
			return Status::CANCELLED;
		}
	}
};

using grpc::Channel;
using grpc::ClientContext;
class GreeterClient {
public:
	GreeterClient(std::shared_ptr<Channel> channel)
		: stub_(gameRpcProctoc::ExampleService::NewStub(channel)) {}

	std::string SayHello(const std::string &user) {
		::gameRpcProctoc::Request request;
		request.set_message(user);

		::gameRpcProctoc::Response reply;

		ClientContext context;

		Status status = stub_->SayHello(&context, request, &reply);

		if (status.ok()) {
			return reply.message();
		}
		else {
			std::cout << status.error_code() << ": " << status.error_message()
				<< std::endl;
			return "RPC failed";
		}
	}

private:
	std::unique_ptr<gameRpcProctoc::ExampleService::Stub> stub_;
};

TEST(Protobuf, grpc)
{
	std::string serveraddr("0.0.0.0:50069");
	SendService svc;
	ServerBuilder builder;
	builder.AddListeningPort(serveraddr, grpc::InsecureServerCredentials());
	builder.RegisterService(&svc);
	std::unique_ptr<Server> server(builder.BuildAndStart());
	std::cout << "Server listening on " << serveraddr.c_str() << std::endl;

	std::thread t([]() {
		GreeterClient greeter(grpc::CreateChannel("localhost:50069", grpc::InsecureChannelCredentials()));
		std::string user("world");
		std::string reply = greeter.SayHello(user);
		std::cout << "Greeter received: " << reply << std::endl;
		});
	t.detach();

	server->Wait();
}


int main(int argc, char **argv)
{
	::testing::InitGoogleMock(&argc, argv);
	int ret = RUN_ALL_TESTS();
	return ret;
}
